//
//  GCKViewController.m
//  ChromekeyDemo
//
//  Created by Paul Carff on 2/19/14.
//  Copyright (c) 2014 Paul Carff. All rights reserved.
//

#import "GCKViewController.h"
#import "GCKAppDelegate.h"
#import "CoreMedia/CoreMedia.h"
#import "AVFoundation/AVFoundation.h"

@interface GCKViewController ()

// Local playback
@property (nonatomic, strong) AVPlayerItem *playerItem;
@property (nonatomic, strong) AVPlayer *player;

//Add MediaControlChannel
@property (nonatomic, strong, readwrite) GCKMediaControlChannel *mMCC;

@property (nonatomic, strong) GCKDeviceManager *mDeviceManager;
@property (nonatomic, strong) GCKDeviceScanner *mDeviceScanner;
@property (nonatomic, strong) GCKDeviceFilter *mDeviceFilter;

@property (nonatomic, strong) GCKMediaMetadata *mMetaData;
@property (nonatomic, strong) GCKMediaInformation *mMediaInformation;


@end

@implementation GCKViewController

@synthesize mDeviceManager = mDeviceManager_;
@synthesize mDeviceScanner = mDeviceScanner_;
@synthesize mDeviceFilter = mDeviceFilter_;

@synthesize mMCC = mMCC_;

@synthesize mMetaData = mMediaData_;
@synthesize mMediaInformation = mMediaInformation_;

@synthesize keys = keys_;
@synthesize urls = urls_;
@synthesize mimeTypes = mimeTypes_;
@synthesize data = data_;
@synthesize playPauseButton = playPauseButton_;
@synthesize stopButton = stopButton_;
@synthesize selectDeviceButton = selectDeviceButton_;
@synthesize volumeSlider = volumeSlider_;
@synthesize playProgressSlider = playProgressSlider_;
@synthesize volumeImage = volumeImage_;

static NSString * const kUserAgent = @"net.carff.castapp";
//static NSString *const kReceiverAppID = @"249CB285";
//static NSString *const kReceiverAppID = @"B08584D3";
static NSString *const kReceiverAppID = @"AA3A9C5C";

BOOL playPauseIsPlay = NO;
BOOL willResume = NO;
BOOL stopWasPressedBefore = NO;
BOOL localPlay = YES;
double mediaDuration;
double currentPlayPosition = 0.0;
double playPositionWhenSwitch = 0.0;


#pragma mark - Player Setup

-(void) playMovie {
   NSLog(@"playMovie");
  //Hide Volume slider for local playback
  [self.volumeSlider setHidden:YES];
  [self.volumeImage setHidden:YES];
  [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"pause.png"]
                                  forState:UIControlStateNormal];
  NSLog(@"playMovie");
  if (self.mMCC) {
    playPositionWhenSwitch = self.mMCC.approximateStreamPosition;
    NSLog(@"playPostion _ playMovie: %f", playPositionWhenSwitch);
    //END SESSION?
    [self.mMCC stop];
    
  }
  NSLog(@"playMovie locally");
  NSURL *url = [NSURL URLWithString: mAppDelegate.mediaContent];
  self.playerItem = [AVPlayerItem playerItemWithURL:url];
  if (self.player) {
    [self.player replaceCurrentItemWithPlayerItem:self.playerItem];
  } else {
    self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
  }
  AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
  playerLayer.frame = self.mediaView.bounds;
  CALayer *superLayer = self.mediaView.layer;
  [superLayer addSublayer:playerLayer];
  [self.player addObserver:self forKeyPath:@"status" options:0 context:nil];
  CMTime newTime = CMTimeMakeWithSeconds(playPositionWhenSwitch, 1);
  [self.player seekToTime:newTime];
  [self.player play];
  //[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateStatus) userInfo:nil repeats:YES];
}

-(void)castMovie {
  NSLog(@"Started castMovie");
  //Show Volume slider for m playback
  [self.volumeSlider setHidden:NO];
  [self.volumeImage setHidden:NO];
  [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"pause.png"]
                                  forState:UIControlStateNormal];
  if (self.player) {
    NSLog(@"stopping local player to DEVICE");
    playPositionWhenSwitch = CMTimeGetSeconds([self.player currentTime]);
    NSLog(@"playPostion _ castMovie: %f", playPositionWhenSwitch);
    [self.player pause];
  }
  
  if (mAppDelegate.mDevice) {
    NSLog(@"calling loadMedia");
    [self loadMedia];
  } else {
    NSLog(@" Error - no DEVICE");
  }
}

-(void) updateStatus {
  //Could add other data to monitor but for now just update the progress slider.
  [self updateProgressSlider];
  NSString *nowPlaying = @"Currently playing: ";
  if (mAppDelegate.mediaTitle) {
    //<TODO> Change to using status from SDK
    nowPlaying = [nowPlaying stringByAppendingString:mAppDelegate.mediaTitle];
    //nowPlaying = [nowPlaying stringByAppendingString:mAppDelegate.mDevice.modelName];
    //nowPlaying = [nowPlaying stringByAppendingString:mAppDelegate.mDevice.deviceID];
  }
  self.currentlyPlaying.text = nowPlaying;
  
  //If devices are available show m button
  if (mAppDelegate.mDeviceArray.count > 0) {
    [self.selectDeviceButton setHidden:NO];
  } else {
    [self.selectDeviceButton setHidden:YES];
  }
  if (self.mMCC) {
    //NSLog(@"PlayStatus: %d\n", [self.mMCC playerState]);
  }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change context:(void *)context {
  if (object == self.player && [keyPath isEqualToString:@"status"]) {
    if (self.player.status == AVPlayerStatusReadyToPlay) {
      NSLog(@"Player Ready to Play");
      //playButton.enabled = YES;
    } else if (self.player.status == AVPlayerStatusFailed) {
      // something went wrong. player.error should contain some information
      NSLog(@"Something is wrong with player");
    }
  }
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  
	NSLog(@"GCKMediaTableViewController creating keys");
  // Create the data for display
  self.keys = [NSArray arrayWithObjects:@"Big Buck Bunny", @"HLS Sample", @"SS Sample", @"Dash Sample", @"Tears of Steel", @"Elephant Dreams", @"Marnau the Vampire",
               @"Project London", @"Reel 2012", @"Google IO 2011 Countdown (MUSIC)",  @"Google IO 2011 Walkout (Music)", nil];
  NSLog(@"GCKMediaTableViewController creating urls");
  self.urls = [NSArray arrayWithObjects:@"http://commondatastorage.googleapis.com/gtv-videos-bucket/big_buck_bunny_1080p.mp4",
               @"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8",
               @"http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest",
               @"http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-manifest.mpd",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/tears_of_steel_1080p.webm",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/ED_1280.mp4",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/murnau_the_vampire_(2007)_oscar_alvarado%C2%B4s_480x200.mp4",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/project_london-_official_trailer_1280x720.mp4",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/reel_2012_1280x720.mp4",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/Google%20IO%202011-%2030%20min%20Countdown.mp3",
               @"http://commondatastorage.googleapis.com/gtv-videos-bucket/Google%20IO%202011%2045%20Min%20Walk%20Out.mp3",
               nil];
  NSLog(@"GCKMediaTableViewController creating mimeTypes");
  self.mimeTypes = [NSArray arrayWithObjects:@"video/mp4",
                    @"video/mp4",
                    @"application/vnd.ms-sstr+xml",
                    @"application/dash+xml",
                    @"video/webm",
                    @"video/mp4",
                    @"video/mp4",
                    @"video/mp4",
                    @"video/mp4",
                    @"audio/mp3",
                    @"audio/mp3",
                    nil];
  NSLog(@"GCKMediaTableViewController creating data dictionary");
  self.data = [NSDictionary dictionaryWithObjects:self.urls
                                          forKeys:self.keys];
  
  //Scan ForDevices
  NSLog(@"Adding Device Scannner Listener");
    self.mDeviceScanner = [[GCKDeviceScanner alloc] init];
    self.mDeviceFilter = [[GCKDeviceFilter alloc] initWithDeviceScanner:self.mDeviceScanner
                                                              criteria:([GCKFilterCriteria
                                                                         criteriaForAvailableApplicationWithID:kReceiverAppID])];
  //[self.mDeviceScanner addListener:self];
  NSLog(@"Calling startScan from viewDidLoad");
  [self startScan];
}


-(void) viewDidAppear:(BOOL)animated {
  [super viewDidAppear:YES];
  [self.mediaTableView reloadData];
  [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(updateStatus) userInfo:nil repeats:YES];
}

-(void) viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
}


- (void)didReceiveMemoryWarning
{
  [super didReceiveMemoryWarning];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
  return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return self.keys.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellIdentifier = @"mediaCell";
  UITableViewCell *mediaCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                               forIndexPath:indexPath];
  //NSLog(@"adding: %@", [self.keys objectAtIndex:indexPath.row]);
  mediaCell.textLabel.text = [self.keys objectAtIndex:indexPath.row];
  return mediaCell;
}


#pragma mark - Media Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  NSString *mediaTitle = [self.keys objectAtIndex:indexPath.row];
  NSString *mediaUrl = [self.data objectForKey:mediaTitle];
  NSString *mimeType = [self.mimeTypes  objectAtIndex:indexPath.row];
  
  NSLog(@"Content Selected: %@" , mediaTitle);
  mAppDelegate.mediaContent = mediaUrl;
  mAppDelegate.mediaTitle = mediaTitle;
  mAppDelegate.mimeType = mimeType;
 
  NSLog(@"Local Play is: %d", localPlay);
  if (localPlay) {
    NSLog(@"LOCAL Selected");
    [self playMovie];
  } else {
    NSLog(@"Cast to Chromecast Selected");
    [self castMovie];
  }
}

#pragma mark - Media Controls


-(IBAction)changeVolume:(UISlider *)sender {
  if (!localPlay) {
    if (self.mMCC) {
      
        
      //double currentVolume = self.mMCC.volume;
      double sliderValue = self.volumeSlider.value;
      [self.volumeSlider setValue:sliderValue animated:YES];
      [self.mDeviceManager setVolume:sliderValue];
//      [self.mMCC setStreamVolume:sliderValue];
    } else {
      NSLog(@"changeVolume - mMCC==null");
    }
  }
}

- (IBAction)playPauseVideo:(UIButton *)sender {
  //FIX THIS
  self.playPauseButton = sender;
  NSLog(@"playPauseIsPlay: %d", playPauseIsPlay);
  if (localPlay) {
    if (playPauseIsPlay) {
      NSLog(@"Play button PRESSED");
      [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"pause.png"]
                                      forState:UIControlStateNormal];
      stopWasPressedBefore = !stopWasPressedBefore;
      [self.player play];
    } else {
      NSLog(@"Pause button PRESSED");
      [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"play.png"]
                                      forState:UIControlStateNormal];
      [self.player pause];
    }
    playPauseIsPlay = !playPauseIsPlay;
  } else {
    if (self.mMCC) {
      if (playPauseIsPlay) {
        NSLog(@"CASTING Play button PRESSED");
        if (stopWasPressedBefore) {
          [self.mMCC play];
          stopWasPressedBefore = !stopWasPressedBefore;
        } else {
          [self.mMCC play];
        }
        [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"pause.png"]
                                        forState:UIControlStateNormal];
      } else {
        NSLog(@"CASTING Pause button PRESSED");
        if (self.mMCC) {
          [self.mMCC pause];
          [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"play.png"]
                                          forState:UIControlStateNormal];
        }
      }
      playPauseIsPlay = !playPauseIsPlay;
      
    } else {
      NSLog(@"playPauseVideo - mMCC==null");
    }
  }
}

- (IBAction)stopVideo:(UIButton *)sender {
  
  NSLog(@"Stop button PRESSED");
  playPauseIsPlay = YES;
  if (localPlay) {
    [self.player pause];
  } else {
    if (self.mMCC) {
      [self.mMCC stop];
      stopWasPressedBefore = !stopWasPressedBefore;
    } else {
      NSLog(@"stopVideo - mMCC==null");
    }
  }
  [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"play.png"]
                                  forState:UIControlStateNormal];
}

#pragma mark - Progress Bar Controls
-(IBAction)changePlayPosition:(id)sender {
  
  float percent = self.playProgressSlider.value;
  NSLog(@"play position slider value: %f", percent);
  
  if (localPlay) {
    // NOTE THAT THIS IS A BIT SLOW.
    double duration = CMTimeGetSeconds([self.playerItem duration]);
    NSLog(@"playerDuration: %f", duration);
    CMTime newTime = CMTimeMakeWithSeconds((percent * duration), 1);
    
    NSLog(@"Scrubbung to: %f", percent * duration);
    [self.player seekToTime:newTime];
    [self.player play];
    
  } else {
    if (self.mMCC) {
      
      NSTimeInterval newTime = percent * self.mMCC.mediaStatus.mediaInformation.streamDuration;
      [self.mMCC seekToTimeInterval:newTime];
      //[self.mMCC play];
    }
  }
  [self.playPauseButton setBackgroundImage:[UIImage imageNamed:@"pause.png"]
                                  forState:UIControlStateNormal];
  playPauseIsPlay = NO;
}

-(void) updateProgressSlider {
  if (localPlay) {
    if (self.player) {
      self.playProgressSlider.value = CMTimeGetSeconds([self.player currentTime])/CMTimeGetSeconds([self.playerItem duration]) ;
    }
  } else {
    if (self.mMCC) {
      float percent =[self.mMCC approximateStreamPosition]/self.mMCC.mediaStatus.mediaInformation.streamDuration;
      self.playProgressSlider.value = percent;
    }
  }
}

#pragma mark - ActionSheet for device selection
-(BOOL) isIpad {
  if ([(NSString*)[UIDevice currentDevice].model isEqualToString:@"iPad"]) {
    return YES;
  } else {
    return NO;
  }
}

-(IBAction)showActionSheet:(id)sender {
  //Automatically Launch when only one device is available
  //If !casting then cast else go local
  // Change this to add button for each device
  UIActionSheet *deviceSelection = [[UIActionSheet alloc]
                                    initWithTitle:@"Select a Device"
                                    delegate:self
                                    cancelButtonTitle:[self isIpad] ? nil : @"Cancel"
                                    destructiveButtonTitle:nil
                                    otherButtonTitles:@"Disconnect", nil];
 //add m devices
//  for (GCKDevice *dev in mAppDelegate.mDeviceArray){
  //for (GCKDevice *dev in mAppDelegate.deviceScanner.devices) {
for(GCKDevice *dev in self.mDeviceFilter.devices) {
    [deviceSelection addButtonWithTitle:dev.friendlyName];
  }
  deviceSelection.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
  [deviceSelection showInView:self.view];
}

-(void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
  NSLog(@"selected button %d", buttonIndex);
  if (buttonIndex == actionSheet.cancelButtonIndex) { return; }
  playPositionWhenSwitch = 0.0;
  if (buttonIndex == actionSheet.firstOtherButtonIndex) {
    NSLog(@"local play selected");
    localPlay = YES;
    if (self.mMCC) {
      playPositionWhenSwitch = self.mMCC.approximateStreamPosition;
      [self.mMCC stop];
      //[self endSession];
    }
    if (self.player.status == AVPlayerStatusReadyToPlay) {
      CMTime newTime = CMTimeMakeWithSeconds(playPositionWhenSwitch, 1);
      [self.player seekToTime:newTime];
      [self.player play];
    }
    // NEED to add castingState if (casting) then   else
    //[self endSession];
    [self deviceDisconnected];
    //[self.selectDeviceButton setBackgroundImage:[UIImage imageNamed:@"device_off.png"]
    //                                   forState:UIControlStateNormal];
    
  } else {
    
    if (self.isIpad) {
      NSLog(@"isIpad - buttonIndex %d", buttonIndex);
      // NEED TO VERIFY THIS
      mAppDelegate.mDevice = [mAppDelegate.mDeviceArray  objectAtIndex:buttonIndex-1];
    } else {
      NSLog(@"isNotIpad - buttonIndex %d", buttonIndex);
      mAppDelegate.mDevice = [mAppDelegate.mDeviceArray  objectAtIndex:buttonIndex-2];
    }
    //Initiate device manager with device and receiver id
    NSLog(@"Allocating Device Manager");
    self.mDeviceManager = [[GCKDeviceManager alloc] initWithDevice:mAppDelegate.mDevice
                                           clientPackageName:kUserAgent];
    NSLog(@"Adding Device Manager Listener");
    self.mDeviceManager.delegate = self;
    NSLog(@"Connecting Device Manager");
    [self.mDeviceManager connect];
    
    localPlay = NO;
    double currentPlayPosition;
    if (self.player.status == AVPlayerStatusReadyToPlay) {
      //Consider playing at current position if already playing
      currentPlayPosition = CMTimeGetSeconds([self.player currentTime]);
      NSLog(@"currentPlayPostion: %f", currentPlayPosition);
      [self castMovie];
    }
    [self.selectDeviceButton setBackgroundImage:[UIImage imageNamed:@"device_on.png"]
                                       forState:UIControlStateNormal];
    NSLog(@"device: %@", mAppDelegate.mDevice.friendlyName);
    
  }
}

-(void)stopScan {
    NSLog(@"stop scanner");
    [self.mDeviceScanner stopScan];
    [self.mDeviceFilter removeDeviceFilterListener:self];
    [self.mDeviceScanner removeListener:self];
   
    if (!willResume) {
        [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(startScan) userInfo:nil repeats:NO];
    }
}

-(void)startScan {
    NSLog(@"start scanner");
    [self.mDeviceScanner addListener:self];
    [self.mDeviceFilter addDeviceFilterListener:self];
    [self.mDeviceScanner startScan];
    [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(stopScan) userInfo:nil repeats:NO];
}


#pragma mark - GCKDeviceScannerListener

-(void)scanStarted {
  if (mAppDelegate.mDeviceArray) {
    NSLog(@"removin objects from deviceArray");
    [mAppDelegate.mDeviceArray removeAllObjects];
  }
  NSLog(@"scanStarted");
  
}

-(void)scanStopped {
  NSLog(@"scanStopped");
  if (mAppDelegate.mDeviceArray.count >0) {
    [self.selectDeviceButton setHidden:NO];
  } else {
    [self.selectDeviceButton setHidden:YES];
  }
}

- (void) deviceDidComeOnline:(GCKDevice *)device forDeviceFilter:(GCKDeviceFilter *)deviceFilter {
  if (!mAppDelegate.mDeviceArray) {
    NSLog(@"Creating device array");
    mAppDelegate.mDeviceArray = [[NSMutableArray alloc]init];
  }
  GCKDevice *existing;
  //Add to Array
  NSUInteger insertIndex;
  for (insertIndex = 0; insertIndex < [mAppDelegate.mDeviceArray count]; ++insertIndex) {
    existing = [mAppDelegate.mDeviceArray objectAtIndex:insertIndex];
    if (([existing.friendlyName caseInsensitiveCompare:device.friendlyName] >= NSOrderedSame)) {
     break;
    }
  }
  if (existing.friendlyName != device.friendlyName) {
    NSLog(@"mDeviceDidComeOnline: %@ - adding to array" , device.friendlyName);
    [mAppDelegate.mDeviceArray insertObject:device atIndex:insertIndex];    
  }

}

- (void)deviceDidGoOffline:(GCKDevice *)device forDeviceFilter:(GCKDeviceFilter *)deviceFilter {
  [mAppDelegate.mDeviceArray removeObject:device];
  NSLog(@"mDeviceDidGoOffLine  %@" , device.friendlyName);
}

#pragma mark - DeviceManagerDelegate

- (void) deviceManagerDidConnect:(GCKDeviceManager *)deviceManager {
  NSLog(@"Device Manager Connected.");
  [self.mDeviceManager launchApplication:kReceiverAppID];
}

- (void)deviceManager:(GCKDeviceManager *)deviceManager
        didConnectToCastApplication:(GCKApplicationMetadata *)applicationMetadata
                          sessionID:(NSString *)sessionID
                launchedApplication:(BOOL)launchedApplication{
  self.mMCC = [[GCKMediaControlChannel alloc] init];
  self.mMCC.delegate = self;
  [self.mDeviceManager addChannel:self.mMCC];
}

-(void)deviceManager:(GCKDeviceManager *)deviceManager didDisconnectFromApplicationWithError:(NSError *)error {
  NSLog(@"Received notification that device disconnected from application");
  if (error != nil) {
    //Received error
    
  }
  [self deviceDisconnected];
}

-(void)deviceManager:(GCKDeviceManager *)deviceManager didDisconnectWithError:(NSError *)error {
  NSLog(@"Received notification that device disconnected");
  if (error != nil) {
    //Received error
    
  }
  [self deviceDisconnected];
}



- (void)deviceDisconnected {
  [self.selectDeviceButton setBackgroundImage:[UIImage imageNamed:@"device_off.png"]
                                     forState:UIControlStateNormal];
  localPlay = YES;
  NSLog(@"Trying to disconnect device");
  [self.mDeviceManager stopApplication];
  self.mMCC = nil;
  self.mDeviceManager = nil;
  mAppDelegate.mDevice = nil;
}

-(void)loadMedia {
  GCKMediaMetadata *metadata = [[GCKMediaMetadata alloc] init];
  [metadata setString:mAppDelegate.mediaTitle forKey:kGCKMetadataKeyTitle];
  //<TODO> Might be optional since I don't have thumbnails yet.
  //[metadata addMediaImage:[[GCKImage alloc] initWithURL:thumbnailURL width:100 height:100]];
  NSURL *url = [[NSURL alloc] initWithString:mAppDelegate.mediaContent];

  NSLog(@"url: %@", url);
  NSLog(@"mimeType: %@", mAppDelegate.mimeType);
  self.mMediaInformation = [[GCKMediaInformation alloc]
                                           initWithContentID:[url absoluteString]
                                           streamType:GCKMediaStreamTypeNone
                                           contentType:mAppDelegate.mimeType
                                           metadata:nil
                                           streamDuration:0
                                           customData:nil];
  NSLog(@"mediaInformation done.");
  NSLog(@"calling loadMedia");

  [self.mMCC loadMedia:self.mMediaInformation
              autoplay:true
          playPosition:0];
  
   NSLog(@"loadMedia complete");

}

-(void) didReceiveMessage: (id) message {
  NSLog(@"Message: %@" , message);
}

@end
